package com.jgzx.security.aspect;

import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.SecureUtil;
import com.alibaba.fastjson.JSON;
import com.jgzx.common.ResultCode;
import com.jgzx.constant.Constants;
import com.jgzx.exception.BizException;
import com.jgzx.redis.config.CacheKeyEnum;
import com.jgzx.redis.config.RedisEnum;
import com.jgzx.redis.service.RedisService;
import com.jgzx.security.annotation.ReSubmit;
import com.jgzx.utils.IpUtil;
import com.jgzx.utils.WebUtil;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;

/**
 * @author jackesy
 * @className: ReSubmitAspect
 * @description: 表单重复提交处理
 * @create 2021/2/6 18:42
 **/
@Aspect
@Component
public class ReSubmitAspect {

    public static final int SUBMIT_EXPIRE = 2; //单位秒

    private static final String SPLIT = "#";

    @Autowired
    public RedisService redisService;

    /**
     * 防止表单重复提交
     *
     * @param point
     * @return
     * @throws Throwable
     */
    @Around("@annotation(com.jgzx.security.annotation.ReSubmit)")
    public Object around(ProceedingJoinPoint point) throws Throwable {
        //1、没有该注解直接放过
        Signature signature = point.getSignature();
        MethodSignature methodSignature = (MethodSignature) signature;
        Method method = methodSignature.getMethod();
        ReSubmit annotation = method.getAnnotation(ReSubmit.class);
        if (annotation == null) {
            return point.proceed();
        }
        //2、className#methodName#ip#url#userAgent#token#param
        HttpServletRequest request = WebUtil.getRequest();
        String className = method.getDeclaringClass().getName();
        String methodName = method.getName();
        String ip = IpUtil.getIpAddr(request);
        String url = request.getRequestURL().toString();
        String token = request.getHeader(Constants.HEADER_TOKEN);
        String userAgent = request.getHeader("User-Agent");
        StringBuilder submit_form = new StringBuilder();
        submit_form.append(className)
                .append(SPLIT).append(methodName)
                .append(SPLIT).append(ip)
                .append(SPLIT).append(url)
                .append(SPLIT).append(userAgent)
                .append(SPLIT).append(token);
        //请求参数
        if (point.getArgs() != null) {
            for (Object obj : point.getArgs()) {
                submit_form.append(SPLIT).append(JSON.toJSONString(obj));
            }
        }
        String value = submit_form.toString();
        String key = CacheKeyEnum.RESUBMIT_KEY.getValue() + SecureUtil.md5(value);
        String redis_value = redisService.get(RedisEnum.LOCK_CACHE, key);
        if (StrUtil.isNotEmpty(redis_value)) {
            throw new BizException(ResultCode.RESUBMIT, "操作太快,重复提交了");
        }
        redisService.set(RedisEnum.LOCK_CACHE, key, value, SUBMIT_EXPIRE);
        return point.proceed();
    }
}
